"""
    create by IAmFiveHigh on 2024/6/9
"""
from typing import Tuple

import numpy as np

from LA.Matrix import Matrix
from LA.LinearSystem import rank, inverse


def matrix_to_nparray(m: 'Matrix'):
    return np.array([
        [m.item(i, j) for j in range(m.col_num())]
        for i in range(m.row_num())
    ])


def diagonalize(A: 'Matrix') -> Tuple['Matrix', 'Matrix', 'Matrix']:
    if A.row_num() != A.col_num():
        raise Exception("Error: 对角化的矩阵必须是方阵")

    m = matrix_to_nparray(A)
    eigenvalues, eigenvectors = np.linalg.eig(m)
    # PDP的逆 P就是特征向量组成的矩阵
    P = Matrix(eigenvectors.tolist())

    if rank(P) != A.col_num():
        # 通过矩阵的秩判断P是否可逆,不可逆原矩阵不能被对角化
        raise Exception(f"Error: 矩阵{A}不能被对角化")

    # PDP的逆 D就是特征值排成的对角矩阵
    D = Matrix.diagonal(eigenvalues.tolist())
    # PDP的逆 P的逆就是P的逆
    Pinv = inverse(P)

    return P, D, Pinv


if __name__ == '__main__':
    try:
        matrix = Matrix([[3, 2], [1, 2]])
        print(f"矩阵{matrix}的对角矩阵是{diagonalize(matrix)[1]}")
    except Exception as e:
        print(e)

    try:
        matrix2 = Matrix([[3, 1], [0, 3]])
        print(diagonalize(matrix2))
    except Exception as e:
        print(e)
